package com.qf.blogsystem.core.controller;

import com.alibaba.druid.util.StringUtils;
import com.alibaba.fastjson.JSON;
import com.qf.blogsystem.core.utils.BaseConstants;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.WebContext;
import org.thymeleaf.expression.Strings;
import org.thymeleaf.templatemode.TemplateMode;
import org.thymeleaf.templateresolver.ServletContextTemplateResolver;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

/**
 * 公共Servlet,供其他Servlet继承
 */
@WebServlet("/BaseServlet")
public class BaseServlet extends HttpServlet {
    /**
     * 声明请求和响应对象
     */
    protected HttpServletRequest request;
    protected HttpServletResponse response;
    /**
     * 声明模板引擎对象
     */
    protected TemplateEngine templateEngine;

    /**
     * servlet初始化的时候创建模板引擎对象
     * @throws ServletException
     */
    @Override
    public void init() throws ServletException {
        //获取上下文对象
        ServletContext servletContext=this.getServletContext();
        //创建模板解析对象
        ServletContextTemplateResolver templateResolver=new ServletContextTemplateResolver(servletContext);
        //设置模板解析对象参数
        //设置模板模式HTML
        templateResolver.setTemplateMode(TemplateMode.HTML);
        //设置前缀
        templateResolver.setPrefix(servletContext.getContextPath()+"/WEB-INF/templates/");
        //设置后缀
        templateResolver.setSuffix(".html");
        //设置是否开启缓存
        templateResolver.setCacheable(false);
        //设置编码方式
        templateResolver.setCharacterEncoding("utf-8");

        //创建模板引擎对象
        templateEngine=new TemplateEngine();
        //给模板引擎对象设置模板解析器
        templateEngine.setTemplateResolver(templateResolver);

    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //给请求和响应对象赋值
        this.request=request;
        this.response=response;
        //获取用户请求时调用的action
        String action = getActionName(request.getRequestURI());
        //判断action是否为空
        if (action==null){
            return;
        }
        //根据actionName找到要调用的对应的方法
        Method method=null;
        try {
            method=getActionMethod(action);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }

        String result;
        try {
            //用方法对象调用方法
            result=invokeAction(method);
            //响应客户端
            if (!StringUtils.isEmpty(result)){
                responseClient(result);
            }
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }



    }

    /**
     * 从请求地址中找到要调用的action方法
     * @param requestURI
     * @return String
     */
    private String getActionName(String requestURI) {
        return requestURI.substring(requestURI.lastIndexOf("/")+1);
    }

    /**
     * 根据acionName获得要调用的方法对象
     * @param action
     * @return Method
     */
    private Method getActionMethod(String action) throws NoSuchMethodException {
        return this.getClass().getDeclaredMethod(action);
    }

    /**
     * 根据方法对象调用方法
     * @param method
     * @return String
     */
    private String invokeAction(Method method) throws InvocationTargetException, IllegalAccessException {
        return (String) method.invoke(this);
    }

    /**
     * 根据方法返回值响应客户端
     * @param result
     */
    private void responseClient(String result) throws ServletException, IOException {
        int index = result.indexOf(":");
        //获得跳转的方式
        String type=result.substring(0,index);
        //获得要跳转的页面
        String page=result.substring(index+1);
        //获得项目的根目录
        String contextPath = request.getContextPath();
        if (BaseConstants.BASE_FORWARD.equals(type)){
            //以转发的形式响应客户端
            request.getRequestDispatcher(page).forward(request,response);
        }else if (BaseConstants.BASE_REDIRECT.equals(type)){
            //以重定向的形式响应客户端
            response.sendRedirect(contextPath+"/"+page);
        }else if (BaseConstants.BASE_SCRIPT.equals(type)){
            //以弹窗的形式响应客户端
            response.getWriter().write("<script>alert('" + page + "');</script>");
        }else if (BaseConstants.BASE_JSON.equals(type)){
            //以JSON字符串的形式响应客户端
            response.getWriter().write(page);
        }
    }

    /**
     * 根据业务层返回结果做出响应
     * @param flag
     * @param url
     * @return String
     */
    protected String outRedirect(Boolean flag, String url){
        if (!flag) {
            return BaseConstants.BASE_SCRIPT + ":操作失败";
        }
        return BaseConstants.BASE_REDIRECT + ":" + url;
    }

    /**
     * 根据结果做出JSON响应
     * @param code
     * @param msg
     * @return String
     */
    protected String outJson(Integer code, String msg) {
        Map<String, Object> map = new HashMap<>();
        map.put("code", code);
        map.put("msg", msg);
        String jsonString = JSON.toJSONString(map);
        return BaseConstants.BASE_JSON + ":" + jsonString;
    }

    /**
     * 用thymeleaf模板响应页面
     * @param viewName
     * @param data
     * @throws IOException
     */
    protected void outView(String viewName, Map<String, Object> data) throws IOException {
        //创建webContext对象
        WebContext webContext=new WebContext(request,response,this.getServletContext());
        //把数据放到webContext对象对象中
        webContext.setVariables(data);
        //处理模板数据并响应
        templateEngine.process(viewName,webContext,response.getWriter());
    }

}
